#include <QtCore/QDebug>
#include "hssudoku.h"
#include <QtGui/QGraphicsProxyWidget>
#include <QtGui/QGraphicsGridLayout>
#include <QtGui/QMessageBox>
#include <QtCore/QSettings>
#include <QtGui/QCloseEvent>
#include <QtCore/QTimer>
#include "sudokutable.h"
#include "sudokuitemwidget.h"
#include "scoredialog.h"
#include "resultdialog.h"
#include "gvalues.h"
#include "hssudokuconfigure.h"
#include "optionsdialog.h"
#include "help-browser/helpbrowser.h"


hssudoku::hssudoku(QWidget *parent, Qt::WindowFlags flags): QMainWindow(parent, flags), ui(new Ui::MainWindow), complexity(0.0), firstPaint(true)
{
	ui->setupUi(this);
	sTable = new SudokuTable(this);
	scene = new QGraphicsScene(this);
	layout = new QGraphicsGridLayout;
	form = new QGraphicsWidget;
	timer = new QTimer(this);
	scoreDialog = new ScoreDialog(this);
	resultDialog = new ResultDialog(this);
	optionsDialog = new OptionsDialog(this);
	playTime.setHMS(0, 0, 0);

	settings = new QSettings(QSettings::NativeFormat, QSettings::UserScope, "HsSudoku", QString(), this);

	readSettings();

	if(!dataDir.exists())
	{
		dataDir.cdUp();
		dataDir.mkdir(".hssudoku");
	}

	sTable->setComplexity(complexity);
	initTable();
	initView();

	ui->graphicsView->setScene(scene);

	initShow();

	setWindowTitle(trUtf8("Судоку ") + VERSION);

	ui->complHorizontalSlider->setValue((complexity - SS::MIN_COMPLEXITY) / 0.004);
	timer->setInterval(1000);
	connect(timer, SIGNAL(timeout()), SLOT(timer_out()));
	timer->start();
}

hssudoku::~hssudoku()
{
	delete ui;
}

void hssudoku::on_checkButton_clicked()
{
	timer->stop();

	if(sTable->convergence())
	{
		QMessageBox::information(this, trUtf8("Проверка сходимости головоломки"), trUtf8("Всё сходится!"));
		getScore();

	}

	else
	{
		QMessageBox::information(this, trUtf8("Проверка сходимости головоломки"), trUtf8("Не сходится!"));
		timer->start();
	}
}

void hssudoku::on_newButton_clicked()
{
	complexity = SS::MIN_COMPLEXITY + qreal(ui->complHorizontalSlider->value()) * 0.004;

	viewItemsList.clear();
	viewSudokuItemsList.clear();
	scene->clear();
	sTable->clear();

	layout = new QGraphicsGridLayout;
	form = new QGraphicsWidget;
	sTable->setComplexity(complexity);

	initTable();
	initView();
	initShow();

	playTime.setHMS(0, 0, 0);

	if(!timer->isActive())
		timer->start();
}

void hssudoku::initTable()
{
	sTable->generate();

	for(int i = 0; i < SS::TABLE_SIZE; i++)
	{
		viewSudokuItemsList.append(QList<SudokuItemWidget *>());

		for(int j = 0; j < SS::TABLE_SIZE; j++)
		{
			SudokuItemWidget *it = new SudokuItemWidget;
			it->setFont(viewFont);
			it->setStaticColor(staticColor);
			it->setDynColor(dynamicColor);
			it->setSudokuItem(sTable->getSudokuItem(i, j));
			it->setAlignment(Qt::AlignCenter);
			it->setKofFontSizeBig(fontSizeBig);
			it->setKofFontSizeSmall(fontSizeSmall);
			viewSudokuItemsList[i].append(it);
		}
	}
}

void hssudoku::initView()
{
	for(int i = 0; i < SS::TABLE_SIZE; i++)
	{
		viewItemsList.append(QList<QGraphicsProxyWidget *>());

		for(int j = 0; j < SS::TABLE_SIZE; j++)
		{
			QGraphicsProxyWidget *gw = scene->addWidget(viewSudokuItemsList.at(i).at(j));
			layout->addItem(gw, i, j);
			viewItemsList[i].append(gw);
		}
	}

	form->setLayout(layout);
	scene->addItem(form);
	form->resize(400, 400);
}

void hssudoku::initShow()
{
	QBrush br(QColor(50, 50, 50));
	QPen pen(br, 5);
	qreal xl1 = viewItemsList.at(0).at(2)->pos().x() + viewItemsList.at(0).at(2)->boundingRect().width() + 1;
	qreal xl2 = xl1;
	qreal yl1 = viewItemsList.at(0).at(2)->pos().y();
	qreal yl2 = viewItemsList.at(8).at(2)->pos().y() + viewItemsList.at(8).at(2)->boundingRect().height();
	qreal xl3 = viewItemsList.at(0).at(5)->pos().x() + viewItemsList.at(0).at(5)->boundingRect().width() + 1;
	qreal xl4 = xl3;
	qreal xl5 = viewItemsList.at(3).at(0)->pos().x();
	qreal xl6 = viewItemsList.at(3).at(8)->pos().x() + viewItemsList.at(3).at(8)->boundingRect().width();
	qreal yl3 = viewItemsList.at(3).at(0)->pos().y() - 1;
	qreal yl4 = yl3;
	qreal yl5 = viewItemsList.at(6).at(0)->pos().y() - 1;
	qreal yl6 = yl5;

	scene->addLine(xl1, yl1, xl2, yl2, pen);
	scene->addLine(xl3, yl1, xl4, yl2, pen);
	scene->addLine(xl5, yl3, xl6, yl4, pen);
	scene->addLine(xl5, yl5, xl6, yl6, pen);
	scene->addRect(xl5, yl1, xl6 - xl5, yl2 - yl1, pen);
}

void hssudoku::readSettings()
{
	complexity = settings->value("General/Complexity", SS::MIN_COMPLEXITY).toReal();
	restoreGeometry(settings->value("View/Geometry", saveGeometry()).toByteArray());
	viewFont = settings->value("View/ViewFont", QFont("Droid Serif")).value<QFont>();
	fontSizeBig = settings->value("View/FontSizeBig", 31).toFloat();
	fontSizeSmall = settings->value("View/FontSizeSmall", 11).toFloat();
	staticColor = settings->value("View/StaticColor", QColor(0, 95, 0)).value<QColor>();
	dynamicColor = settings->value("View/DynamicColor", QColor()).value<QColor>();
	QString dataDirPath = settings->value("Game/DataDir", QDir::homePath() + QString("/.hssudoku")).toString();
	dataDir.setPath(dataDirPath);
	scoreFileName = settings->value("Game/ScoreFile", QString(dataDir.path() + "/score.dat")).toString();
}

void hssudoku::writeSettings()
{
	settings->setValue("General/Complexity", complexity);
	settings->setValue("View/Geometry", saveGeometry());
	settings->setValue("View/ViewFont", viewFont);
	settings->setValue("View/FontSizeBig", fontSizeBig);
	settings->setValue("View/FontSizeSmall", fontSizeSmall);
	settings->setValue("View/StaticColor", staticColor);
	settings->setValue("View/DynamicColor", dynamicColor);
	settings->setValue("Game/DataDir", dataDir.path());
	settings->setValue("Game/ScoreFile", scoreFileName);
}

void hssudoku::closeEvent(QCloseEvent *event)
{
	writeSettings();
	QWidget::closeEvent(event);
}

void hssudoku::timer_out()
{
	playTime = playTime.addSecs(1);
	ui->labelTime->setText(playTime.toString("H:mm:ss"));
}

void hssudoku::on_pauseButton_toggled(bool checked)
{
	if(checked)
	{
		timer->stop();
		ui->pauseButton->setText(trUtf8("Про&должить"));
		ui->graphicsView->setEnabled(false);

	}

	else
	{
		timer->start();
		ui->pauseButton->setText(trUtf8("П&ауза"));
		ui->graphicsView->setEnabled(true);
	}
}

void hssudoku::resizeEvent(QResizeEvent *event)
{
	if(!firstPaint)
	{
		qreal scaleW = 1.0, scaleH = 1.0;
		QSizeF oldSz = event->oldSize();
		QSizeF sz = size();

		scaleW = sz.width() / oldSz.width();
		scaleH = sz.height() / oldSz.height();
		ui->graphicsView->scale(scaleW, scaleH);
	}

	firstPaint = false;

	QWidget::resizeEvent(event);
}

void hssudoku::getScore()
{
	quint32 sc = 0;
	quint32 time = playTime.hour() * 3600 + playTime.minute() * 60 + playTime.second();

	sc = (qreal(SS::MAX_SCORE) - qreal(time) * SS::ONE_SCORE) * complexity;

	scoreDialog->setScore(sc);
	scoreDialog->setScoreDataFileName(scoreFileName);

	if(scoreDialog->exec() == QDialog::Accepted)
	{
		resultDialog->setScoreDataFileName(scoreFileName);
		resultDialog->show();
	}
}

void hssudoku::on_optionsButton_clicked()
{
	optionsDialog->setParams(viewFont, staticColor, dynamicColor);

	if(optionsDialog->exec() == QDialog::Accepted)
	{
		optionsDialog->getParams(viewFont, staticColor, dynamicColor);

		for(int i = 0; i < SS::TABLE_SIZE; i++)
		{
			for(int j = 0; j < SS::TABLE_SIZE; j++)
			{
				viewSudokuItemsList[i][j]->setStaticColor(staticColor);
				viewSudokuItemsList[i][j]->setDynColor(dynamicColor);
				viewSudokuItemsList[i][j]->setFont(viewFont);
			}
		}
	}
}

void hssudoku::on_aboutQtButton_clicked()
{
	qApp->aboutQt();
}

void hssudoku::on_aboutButton_clicked()
{
	QString str1, str2, str3, str4;
	
	str1 = trUtf8("<h2>%1 %2</h2><p><b>%1</b> - игра-головоломка \"Судоку\". Написана на Qt-C++.</p><p>Copyright &copy;  2012 Роман Браун</p>").arg(APP_NAME).arg(VERSION);
	str2 = trUtf8("<p>Это программа является свободным программным обеспечением. Вы можете распространять и/или модифицировать её согласно условиям Стандартной Общественной Лицензии GNU, опубликованной Фондом Свободного Программного Обеспечения, версии 3 или, по Вашему желанию, любой более поздней версии.</p>");
	str3 = trUtf8("<p>Эта программа распространяется в надежде, что она будет полезной, но БЕЗ ВСЯКИХ ГАРАНТИЙ, в том числе подразумеваемых гарантий ТОВАРНОГО СОСТОЯНИЯ ПРИ ПРОДАЖЕ и ГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННОГО ПРИМЕНЕНИЯ. Смотрите Стандартную Общественную Лицензию GNU для получения дополнительной информации.</p>");
	str4 = trUtf8("<p>Вы должны были получить копию Стандартной Общественной Лицензии GNU вместе с программой. В случае её отсутствия, посмотрите <a href=\"http://www.gnu.org/licenses/\">http://www.gnu.org/licenses/</a>.</p><p>E-Mail: <a href=\"mailto:firdragon76@gmail.com\">firdragon76@gmail.com</a><br>Сайт программы: <a href=\"http://code.google.com/p/%1/\">code.google.com/p/%1/</a></p>").arg(APP_FILE_NAME);
	
	QMessageBox::about(this, trUtf8("О программе"), str1 + str2 + str3 + str4);
}

void hssudoku::on_helpButton_clicked()
{
	QString docDir;
	#ifdef Q_OS_LINUX
	docDir = APP_PATH + "/share/doc/" + APP_FILE_NAME + "/html";
	#endif
	#ifdef Q_OS_WIN
	docDir = "doc/html";
	#endif
	HelpBrowser::showPage(docDir, "index.html");
}

#include "hssudoku.moc"


